home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Archives / GNU / GNUPLOTsrc.lha / parse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-22  |  12.6 KB  |  627 lines

  1. #ifndef lint
  2. static char    *RCSid = "$Id: parse.c,v 1.51 1995/12/02 22:04:35 drd Exp $";
  3. #endif
  4.  
  5.  
  6. /* GNUPLOT - parse.c */
  7. /*
  8.  * Copyright (C) 1986 - 1993   Thomas Williams, Colin Kelley 
  9.  *
  10.  * Permission to use, copy, and distribute this software and its documentation
  11.  * for any purpose with or without fee is hereby granted, provided that the
  12.  * above copyright notice appear in all copies and that both that copyright
  13.  * notice and this permission notice appear in supporting documentation. 
  14.  *
  15.  * Permission to modify the software is granted, but not the right to distribute
  16.  * the modified code.  Modifications are to be distributed as patches to
  17.  * released version. 
  18.  *
  19.  * This software is provided "as is" without express or implied warranty. 
  20.  *
  21.  *
  22.  * AUTHORS 
  23.  *
  24.  * Original Software: Thomas Williams,  Colin Kelley. 
  25.  *
  26.  * Gnuplot 2.0 additions: Russell Lang, Dave Kotz, John Campbell. 
  27.  *
  28.  * Gnuplot 3.0 additions: Gershon Elber and many others. 
  29.  *
  30.  */
  31.  
  32. #include <signal.h>
  33. #include <math.h>
  34. #include "plot.h"
  35. #include "help.h"
  36.  
  37.  
  38. RETSIGTYPE fpe __P((int an_int));
  39. static void extend_at __P((void));
  40. static union argument * add_action __P((enum operators sf_index));
  41. static void express __P((void));
  42. static void xterm __P((void));
  43. static void aterm __P((void));
  44. static void bterm __P((void));
  45. static void cterm __P((void));
  46. static void dterm __P((void));
  47. static void eterm __P((void));
  48. static void fterm __P((void));
  49. static void gterm __P((void));
  50. static void hterm __P((void));
  51. static void factor __P((void));
  52. static void xterms __P((void));
  53. static void aterms __P((void));
  54. static void bterms __P((void));
  55. static void cterms __P((void));
  56. static void dterms __P((void));
  57. static void eterms __P((void));
  58. static void fterms __P((void));
  59. static void gterms __P((void));
  60. static void hterms __P((void));
  61. static void iterms __P((void));
  62. static void unary __P((void));
  63.  
  64. static struct at_type *at=NULL;
  65. static int at_size=0;
  66. #if defined(_Windows) && !defined(WIN32)
  67. static jmp_buf far fpe_env;
  68. #else
  69. static jmp_buf  fpe_env;
  70. #endif
  71.  
  72. #define dummy (struct value *) 0
  73.  
  74. RETSIGTYPE fpe(an_int)
  75. int an_int;
  76. {
  77. #if defined(MSDOS) && !defined(__EMX__) && !defined(DJGPP) && !defined(_Windows) || defined(DOS386)
  78.     /* thanks to lotto@wjh12.UUCP for telling us about this  */
  79.     _fpreset();
  80. #endif
  81.  
  82. #ifdef OS2
  83.     (void) signal(an_int, SIG_ACK);
  84. #else
  85.     (void)signal(SIGFPE, (sigfunc)fpe);
  86. #endif
  87.     undefined = TRUE;
  88.     longjmp(fpe_env, TRUE);
  89. }
  90.  
  91.  
  92. #ifdef apollo
  93. #include <apollo/base.h>
  94. #include <apollo/pfm.h>
  95. #include <apollo/fault.h>
  96.  
  97. /*
  98.  * On an Apollo, the OS can signal a couple errors that are not mapped into
  99.  * SIGFPE, namely signalling NaN and branch on an unordered comparison.  I
  100.  * suppose there are others, but none of these are documented, so I handle
  101.  * them as they arise. 
  102.  *
  103.  * Anyway, we need to catch these faults and signal SIGFPE. 
  104.  */
  105.  
  106. pfm_$fh_func_val_t apollo_sigfpe(pfm_$fault_rec_t & fault_rec)
  107. {
  108.     kill(getpid(), SIGFPE);
  109.     return pfm_$continue_fault_handling;
  110. }
  111.  
  112. apollo_pfm_catch()
  113. {
  114.     status_$t status;
  115.     pfm_$establish_fault_handler(fault_$fp_bsun, pfm_$fh_backstop,
  116.                        apollo_sigfpe, &status);
  117.     pfm_$establish_fault_handler(fault_$fp_sig_nan, pfm_$fh_backstop,
  118.                        apollo_sigfpe, &status);
  119. }
  120. #endif
  121.  
  122.  
  123. void evaluate_at(at_ptr, val_ptr)
  124.     struct at_type *at_ptr;
  125.     struct value   *val_ptr;
  126. {
  127.     double          temp, real();
  128.  
  129.     undefined = FALSE;
  130.     errno = 0;
  131.     reset_stack();
  132.  
  133. #ifndef DOSX286
  134.     if (setjmp(fpe_env))
  135.         return;        /* just bail out */
  136.     (void)signal(SIGFPE, (sigfunc)fpe);
  137. #endif
  138.  
  139.     execute_at(at_ptr);
  140.  
  141. #ifndef DOSX286
  142.     (void)signal(SIGFPE, SIG_DFL);
  143. #endif
  144.  
  145.     if (errno == EDOM || errno == ERANGE) {
  146.         undefined = TRUE;
  147.     } else {
  148.         (void)pop(val_ptr);
  149.         check_stack();
  150.     /* At least one machine (ATT 3b1) computes Inf without a SIGFPE */
  151.         temp = real(val_ptr);
  152.         if (temp > VERYLARGE || temp < -VERYLARGE) {
  153.             undefined = TRUE;
  154.         }
  155.     }
  156. }
  157.  
  158.  
  159. struct value   *
  160. const_express(valptr)
  161.     struct value   *valptr;
  162. {
  163.     register int    tkn = c_token;
  164.     if (END_OF_COMMAND)
  165.         int_error("constant expression required", c_token);
  166.     dummy_func=NULL;  /* div - no dummy variables in a constant expression */
  167.     evaluate_at(temp_at(), valptr);    /* run it and send answer back */
  168.     if (undefined) {
  169.         int_error("undefined value", tkn);
  170.     }
  171.     return (valptr);
  172. }
  173.  
  174.  
  175. /* if dummy_dunc=NULL on entry, do not attempt to compile dummy variables - div */
  176. struct at_type *
  177. temp_at()
  178. {                /* build a static action table and return its
  179.                  * pointer */
  180.  
  181.     if(at!=NULL) {
  182.         free(at);
  183.         at=NULL;
  184.     }
  185.  
  186.     at=(struct at_type *)alloc(sizeof(struct at_type), "action table");
  187.  
  188.     at->a_count = 0;    /* reset action table !!! */
  189.     at_size=MAX_AT_LEN;
  190.     express();
  191.     return (at);
  192. }
  193.  
  194.  
  195. /* build an action table, put it in dynamic memory, and return its pointer */
  196.  
  197. struct at_type *
  198. perm_at()
  199. {
  200.     register struct at_type *at_ptr;
  201.     unsigned int len;
  202.  
  203.     (void)temp_at();
  204.     len = sizeof(struct at_type) +
  205.         (int)(at->a_count - MAX_AT_LEN) * (int)sizeof(struct at_entry);
  206.     at_ptr = (struct at_type *) ralloc(at, (unsigned long)len, "perm_at");
  207.     at=NULL; /* invalidate at pointer */
  208.     return (at_ptr);
  209. }
  210.  
  211. static void extend_at()
  212. {
  213.   int newsize=sizeof(struct at_type) + at_size * sizeof(struct at_entry);
  214.  
  215.   at=ralloc(at, newsize, "extend_at");
  216.   at_size+=MAX_AT_LEN;
  217. #ifdef DEBUG_STR
  218.   fprintf(stderr, "Extending at size to %d\n", at_size);
  219. #endif
  220. }
  221.  
  222. #ifdef NOCOPY
  223. /*
  224.  * cheap and slow version of memcpy() in case you don't have one 
  225.  */
  226. memcpy(dest, src, len)
  227.     char           *dest, *src;
  228.     unsigned int    len;
  229. {
  230.     while (len--)
  231.         *dest++ = *src++;
  232. }
  233. #endif                /* NOCOPY */
  234.  
  235.  
  236. /* moved from eval.c, the function is only called from this module */
  237. static union argument *
  238. add_action(sf_index)
  239. enum operators sf_index;        /* index of p-code function */
  240. {
  241.     if (at->a_count >= at_size) {
  242.         extend_at();
  243.     }
  244.     at->actions[at->a_count].index = sf_index;
  245.     return(&(at->actions[at->a_count++].arg));
  246. }
  247.  
  248.  
  249. static void express()
  250. {                /* full expressions */
  251.     xterm();
  252.     xterms();
  253. }
  254.  
  255. static void xterm()
  256. {                /* ? : expressions */
  257.     aterm();
  258.     aterms();
  259. }
  260.  
  261.  
  262. static void aterm()
  263. {
  264.     bterm();
  265.     bterms();
  266. }
  267.  
  268.  
  269. static void bterm()
  270. {
  271.     cterm();
  272.     cterms();
  273. }
  274.  
  275.  
  276. static void cterm()
  277. {
  278.     dterm();
  279.     dterms();
  280. }
  281.  
  282.  
  283. static void dterm()
  284. {
  285.     eterm();
  286.     eterms();
  287. }
  288.  
  289.  
  290. static void eterm()
  291. {
  292.     fterm();
  293.     fterms();
  294. }
  295.  
  296.  
  297. static void fterm()
  298. {
  299.     gterm();
  300.     gterms();
  301. }
  302.  
  303.  
  304. static void gterm()
  305. {
  306.     hterm();
  307.     hterms();
  308. }
  309.  
  310.  
  311. static void hterm()
  312. {
  313.     unary();        /* - things */
  314.     iterms();        /* * / % */
  315. }
  316.  
  317.  
  318. static void factor()
  319. {
  320.     register int    value;
  321.  
  322.     if (equals(c_token, "(")) {
  323.         c_token++;
  324.         express();
  325.         if (!equals(c_token, ")"))
  326.             int_error("')' expected", c_token);
  327.         c_token++;
  328.     } else if (equals(c_token,"$")) {
  329.         struct value a;
  330.         if (!isanumber(++c_token))
  331.             int_error("Column number expected", c_token);
  332.         convert(&a, c_token++);
  333.         if (a.type != INTGR || a.v.int_val < 0)
  334.             int_error("Positive integer expected", c_token);
  335.         add_action(DOLLARS)->v_arg = a;
  336.     } else if (isanumber(c_token)) {
  337.         convert(&(add_action(PUSHC)->v_arg), c_token);
  338.         c_token++;
  339.     } else if (isletter(c_token)) {
  340.         if ((c_token + 1 < num_tokens) && equals(c_token + 1, "(")) {
  341.             value = standard(c_token);
  342.             if (value) {    /* it's a standard function */
  343.                 c_token += 2;
  344.                 express();
  345.                 if (equals(c_token, ",")) {
  346.                     while (equals(c_token, ",")) {
  347.                         c_token += 1;
  348.                         express();
  349.                     }
  350.                 }
  351.                 if (!equals(c_token, ")"))
  352.                     int_error("')' expected", c_token);
  353.                 c_token++;
  354.                 (void)add_action(value);
  355.             } else {
  356.                 int             call_type = (int)CALL;
  357.                 value = c_token;
  358.                 c_token += 2;
  359.                 express();
  360.                 if (equals(c_token, ",")) {
  361.                     struct value    num_params;
  362.                     num_params.type = INTGR;
  363.                     num_params.v.int_val = 1;
  364.                     while (equals(c_token, ",")) {
  365.                         num_params.v.int_val += 1;
  366.                         c_token += 1;
  367.                         express();
  368.                     }
  369.                     add_action(PUSHC)->v_arg = num_params;
  370.                     call_type = (int)CALLN;
  371.                 }
  372.                 if (!equals(c_token, ")"))
  373.                     int_error("')' expected", c_token);
  374.                 c_token++;
  375.                 add_action(call_type)->udf_arg = add_udf(value);
  376.             }
  377.         /* dummy_func==NULL is a flag to say no dummy variables active */
  378.         } else if (dummy_func) {
  379.             if (equals(c_token, c_dummy_var[0])) {
  380.                 c_token++;
  381.                 add_action(PUSHD1)->udf_arg = dummy_func;
  382.             } else if (equals(c_token, c_dummy_var[1])) {
  383.                 c_token++;
  384.                 add_action(PUSHD2)->udf_arg = dummy_func;
  385.             } else {
  386.                 int             i, param = 0;
  387.                 for (i = 2; i < MAX_NUM_VAR; i++) {
  388.                     if (equals(c_token, c_dummy_var[i])) {
  389.                         struct value    num_params;
  390.                         num_params.type = INTGR;
  391.                         num_params.v.int_val = i;
  392.                         param = 1;
  393.                         c_token++;
  394.                         add_action(PUSHC)->v_arg = num_params;
  395.                         add_action(PUSHD)->udf_arg = dummy_func;
  396.                         break;
  397.                     }
  398.                 }
  399.                 if (!param) {    /* defined variable */
  400.                     add_action(PUSH)->udv_arg = add_udv(c_token);
  401.                     c_token++;
  402.                 }
  403.             }
  404.         /* its a variable, with no dummies active - div */
  405.         } else {
  406.             add_action(PUSH)->udv_arg = add_udv(c_token);
  407.             c_token++;
  408.         }
  409.     }
  410.     /* end if letter */
  411.     else
  412.         int_error("invalid expression ", c_token);
  413.  
  414.     /* add action code for ! (factorial) operator */
  415.     while (equals(c_token, "!")) {
  416.         c_token++;
  417.         (void)add_action(FACTORIAL);
  418.     }
  419.     /* add action code for ** operator */
  420.     if (equals(c_token, "**")) {
  421.         c_token++;
  422.         unary();
  423.         (void)add_action(POWER);
  424.     }
  425. }
  426.  
  427.  
  428.  
  429. static void xterms()
  430. {                /* create action code for ? : expressions */
  431.  
  432.     if (equals(c_token, "?")) {
  433.         register int    savepc1, savepc2;
  434.         register union argument *argptr1, *argptr2;
  435.         c_token++;
  436.         savepc1 = at->a_count;
  437.         argptr1 = add_action(JTERN);
  438.         express();
  439.         if (!equals(c_token, ":"))
  440.             int_error("expecting ':'", c_token);
  441.         c_token++;
  442.         savepc2 = at->a_count;
  443.         argptr2 = add_action(JUMP);
  444.         argptr1->j_arg = at->a_count - savepc1;
  445.         express();
  446.         argptr2->j_arg = at->a_count - savepc2;
  447.     }
  448. }
  449.  
  450.  
  451. static void aterms()
  452. {                /* create action codes for || operator */
  453.  
  454.     while (equals(c_token, "||")) {
  455.         register int    savepc;
  456.         register union argument *argptr;
  457.         c_token++;
  458.         savepc = at->a_count;
  459.         argptr = add_action(JUMPNZ);    /* short-circuit if already
  460.                          * TRUE */
  461.         aterm();
  462.         argptr->j_arg = at->a_count - savepc;    /* offset for jump */
  463.         (void)add_action(BOOLE);
  464.     }
  465. }
  466.  
  467.  
  468. static void bterms()
  469. {                /* create action code for && operator */
  470.  
  471.     while (equals(c_token, "&&")) {
  472.         register int    savepc;
  473.         register union argument *argptr;
  474.         c_token++;
  475.         savepc = at->a_count;
  476.         argptr = add_action(JUMPZ);    /* short-circuit if already
  477.                          * FALSE */
  478.         bterm();
  479.         argptr->j_arg = at->a_count - savepc;    /* offset for jump */
  480.         (void)add_action(BOOLE);
  481.     }
  482. }
  483.  
  484.  
  485. static void cterms()
  486. {                /* create action code for | operator */
  487.  
  488.     while (equals(c_token, "|")) {
  489.         c_token++;
  490.         cterm();
  491.         (void)add_action(BOR);
  492.     }
  493. }
  494.  
  495.  
  496. static void dterms()
  497. {                /* create action code for ^ operator */
  498.  
  499.     while (equals(c_token, "^")) {
  500.         c_token++;
  501.         dterm();
  502.         (void)add_action(XOR);
  503.     }
  504. }
  505.  
  506.  
  507. static void eterms()
  508. {                /* create action code for & operator */
  509.  
  510.     while (equals(c_token, "&")) {
  511.         c_token++;
  512.         eterm();
  513.         (void)add_action(BAND);
  514.     }
  515. }
  516.  
  517.  
  518. static void fterms()
  519. {                /* create action codes for == and !=
  520.                  * operators */
  521.  
  522.     while (TRUE) {
  523.         if (equals(c_token, "==")) {
  524.             c_token++;
  525.             fterm();
  526.             (void)add_action(EQ);
  527.         } else if (equals(c_token, "!=")) {
  528.             c_token++;
  529.             fterm();
  530.             (void)add_action(NE);
  531.         } else
  532.             break;
  533.     }
  534. }
  535.  
  536.  
  537. static void gterms()
  538. {                /* create action code for < > >= or <=
  539.                  * operators */
  540.  
  541.     while (TRUE) {
  542.         /* I hate "else if" statements */
  543.         if (equals(c_token, ">")) {
  544.             c_token++;
  545.             gterm();
  546.             (void)add_action(GT);
  547.         } else if (equals(c_token, "<")) {
  548.             c_token++;
  549.             gterm();
  550.             (void)add_action(LT);
  551.         } else if (equals(c_token, ">=")) {
  552.             c_token++;
  553.             gterm();
  554.             (void)add_action(GE);
  555.         } else if (equals(c_token, "<=")) {
  556.             c_token++;
  557.             gterm();
  558.             (void)add_action(LE);
  559.         } else
  560.             break;
  561.     }
  562.  
  563. }
  564.  
  565.  
  566.  
  567. static void hterms()
  568. {                /* create action codes for + and - operators */
  569.  
  570.     while (TRUE) {
  571.         if (equals(c_token, "+")) {
  572.             c_token++;
  573.             hterm();
  574.             (void)add_action(PLUS);
  575.         } else if (equals(c_token, "-")) {
  576.             c_token++;
  577.             hterm();
  578.             (void)add_action(MINUS);
  579.         } else
  580.             break;
  581.     }
  582. }
  583.  
  584.  
  585. static void iterms()
  586. {                /* add action code for * / and % operators */
  587.  
  588.     while (TRUE) {
  589.         if (equals(c_token, "*")) {
  590.             c_token++;
  591.             unary();
  592.             (void)add_action(MULT);
  593.         } else if (equals(c_token, "/")) {
  594.             c_token++;
  595.             unary();
  596.             (void)add_action(DIV);
  597.         } else if (equals(c_token, "%")) {
  598.             c_token++;
  599.             unary();
  600.             (void)add_action(MOD);
  601.         } else
  602.             break;
  603.     }
  604. }
  605.  
  606.  
  607. static void unary()
  608. {                /* add code for unary operators */
  609.     if (equals(c_token, "!")) {
  610.         c_token++;
  611.         unary();
  612.         (void)add_action(LNOT);
  613.     } else if (equals(c_token, "~")) {
  614.         c_token++;
  615.         unary();
  616.         (void)add_action(BNOT);
  617.     } else if (equals(c_token, "-")) {
  618.         c_token++;
  619.         unary();
  620.         (void)add_action(UMINUS);
  621.     } else if (equals(c_token, "+")) { /* unary + is no-op */
  622.         c_token++;
  623.         unary();
  624.     } else
  625.         factor();
  626. }
  627.